// Partial
// Partial接收一个泛型类型Type，并将Type所有属性都设置为可选的，返回构造的新类型

interface User {
  name: string;
  age: number;
  address: string;
}
function updateUser(user: User, field: Partial<User>): User {
  return { ...user, ...field };
}

const user: User = { name: "xiaoming", age: 18, address: "beijing" };
const user2 = updateUser(user, { name: "xiaohong" });

console.log(user2);

// Required
// Required接收一个泛型类型Type，并将Type所有属性都设置为必选的，返回构造的新类型（Required的作用与Partial相反）

interface Props {
  name?: string;
  age?: number;
}

function printProps(props: Required<Props>): void {
  console.log(props.name);
  console.log(props.age);
}

// Props 接口定义了可选属性：name?: string 和 age?: number，存在属性为undefined的可能
// printProps 函数要求参数是 Required<Props>，所有属性必须存在且不能为 undefined
// const user3: Props = { name: 'xiaoming', age: 18 } // wrong
const user3: Required<Props> = { name: "xiaoming", age: 18 };
printProps(user3);

// Readonly
// Readonly接收一个泛型类型Type，并将Type所有属性都设置为只读的，返回构造的新类型， 新类型的属性不可再进行分配

const user4: Readonly<User> = { name: "xiaoming", age: 30, address: "beijing" };
// user4.name = 'xiaohong' // 无法为“name”赋值，因为它是只读属性

// Record
// 构造一个对象类型，其属性键为Keys，属性值为Type

type UserName = "xiaoming" | "xiaohong";

const user5: Record<UserName, User> = {
  xiaoming: { name: "xiaoming", age: 18, address: "beijing" },
  xiaohong: { name: "xiaohong", age: 18, address: "beijing" },
};
console.log(user5);

// Pick
// 从类型Type中选择一组属性Keys来创建类型

type NameAndAgeOnly = Pick<User, "name" | "age">;

const user6: NameAndAgeOnly = { name: "xiaoming", age: 18 };
console.log(user6);

// Exclude
type UserExcludeAddress = Exclude<keyof User, "address">;

let key: UserExcludeAddress = "name";
key = "age";
console.log(key);

const a = "a" as const;
const b = "b" as const;
const c = "c" as const;

type ABC = typeof a | typeof b | typeof c;

type AB = Exclude<ABC, "c">;

const _a: AB = "a";

console.log(_a);

// Extract
// 从联合类型Type中提取Union类型然后返回一个新类型

type Person = {
  name: string;
  age: string;
};
const nameKey: Extract<keyof User, keyof Person> = "name"
console.log(nameKey)

// Omit
// 与Pick相反，Omit是从Type中选取所有Keys属性然后删除构造一个新类型

type UserOmitAge = Omit<User, 'age'>;

const user8: UserOmitAge = { name: 'xiaoming', address: 'beijing' };
console.log(user8);

